package com.unionfetch.content_home.ui.auth

import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.text.TextUtils
import com.sumsub.sns.core.SNSMobileSDK
import com.sumsub.sns.core.data.listener.SNSCompleteHandler
import com.sumsub.sns.core.data.listener.TokenExpirationHandler
import com.sumsub.sns.core.data.model.SNSCompletionResult
import com.sumsub.sns.core.data.model.SNSException
import com.sumsub.sns.core.data.model.SNSSDKState
import com.unionfetch.content_home.bean.SumsubAccessToken
import com.unionfetch.content_home.model.KYCAuthModel
import com.unionfetch.content_home.ui.fragment.HomeFragment
import com.unionftech.baselibrary.base.BaseApplication
import com.unionftech.common.CommonConstants
import com.unionftech.common.base.mvp.impl.IBaseCallBack
import com.unionftech.common.bean.ResponseResult
import com.unionftech.common.bean.toast
import com.unionftech.common.common.GlobalInfoManager
import com.unionftech.common.utils.ActivityCollector
import com.unionftech.common.utils.LogUtils
import com.unionftech.common.utils.SpUtils
import com.unionftech.common.widget.LoadingDialog
import java.lang.ref.WeakReference
import java.util.Locale

class SumsubManager private constructor() {
    private val mKYCModel by lazy { KYCAuthModel() }
    private var mLoadingDialog: LoadingDialog? = null

    // sumsub 语言映射
    private val localMap = mutableMapOf<String, Locale>(
        "zh-CN" to Locale.CHINA,
        "zh-TW" to Locale.TAIWAN,
        "en" to Locale.ENGLISH,
        "vn" to Locale("vi", "VN"),
        "th" to Locale("th"),
        "my" to Locale("ms", "MY"),
        "ko" to Locale.KOREAN,
        "ja" to Locale.JAPANESE,
        "fr" to Locale.FRENCH,
        "pt" to Locale("pt"),
        "es" to Locale("es"),
        "ar" to Locale("ar"),
        "de" to Locale("de"),
        "it" to Locale.ITALIAN,
        "hi" to Locale("hi"), // 印度语
        "ru" to Locale("ru"), // 俄语
    )

    companion object {
        private const val TAG = "SumsubManager"
        private const val TYPE_POI = 1
        private const val TYPE_POA = 2

        @Volatile
        private var mInstance: SumsubManager? = null

        fun getInstance() = mInstance ?: synchronized(SumsubManager::class.java) {
            mInstance ?: SumsubManager().also {
                mInstance = it
            }
        }
    }

    private val completedListener = object : SNSCompleteHandler {
        var callBack: (Boolean) -> Unit = { _ -> }
        override fun onComplete(result: SNSCompletionResult, state: SNSSDKState) {
            when (result) {
                is SNSCompletionResult.SuccessTermination -> {
                    LogUtils.d(
                        TAG, "The SDK finished successfully"
                    )
                    callBack.invoke(true)
                }

                is SNSCompletionResult.AbnormalTermination -> {
                    LogUtils.d(
                        TAG, "The SDK got closed because of errors: ${result.exception}"
                    )
                    callBack.invoke(false)
                }
            }
        }

    }

    private val tokenExpirationHandler = object : TokenExpirationHandler {
        override fun onTokenExpired(): String {
            val newToken = "..." // get a new token from your backend
            return newToken
        }
    }

    private val onSDKErrorHandler: (SNSException) -> Unit = { exception ->
        LogUtils.d(TAG, "The SDK throws an exception. Exception: $exception")
        when (exception) {
            is SNSException.Api -> LogUtils.d(TAG, "Api exception. ${exception.description}")
            is SNSException.Network -> LogUtils.d(TAG, "Network exception. $exception")
            is SNSException.Unknown -> LogUtils.d(TAG, "Unknown exception. $exception")
        }
    }

    /**
     * 开启Sumsub Poi身份认证
     */
    fun startSumsubPoi(
        activity: Activity,
        token: String,
        userId: String,
        isSupplement: Boolean,
        isContinuePoa: Boolean,
    ) {
        showLoading(activity)
        //重置POI信息
        resetSumsub(token, userId, TYPE_POI) { resetSuccess ->
            if (resetSuccess) {
                //获取sumsub的poi身份认证token
                getTokenLaunchSumsub(activity, token, userId, TYPE_POI, isSupplement, isContinuePoa)
            } else {
                hideLoading()
                //走手动
                IdentityAuthActivity.startThisBySumsub(activity, isSupplement, isContinuePoa)
            }
        }
    }

    /**
     * 再次尝试拉起sumsub身份认证
     */
    fun startSumsubPoiAgain(
        activity: Activity,
        token: String,
        userId: String,
        isSupplement: Boolean,
    ) {
        showLoading(activity)
        //重置POI信息
        resetSumsub(token, userId, TYPE_POI) resetPoi@{
            //重置POA信息
            resetSumsub(token, userId, TYPE_POA) resetPoa@{ resetSuccess ->
                if (!resetSuccess) {
                    hideLoading()
                    AddressAuthActivity.startThis(activity, isSupplement)
                    ActivityCollector.finishActivity(IdentityAuthActivity::class.java)
                    return@resetPoa
                }
                //获取sumsub的poa身份认证token
                getTokenLaunchSumsub(activity, token, userId, TYPE_POA, isSupplement, false)
            }
        }
    }

    /**
     * 开启 Sumsub Poa地址认证
     */
    fun startSumsubPoa(
        activity: Activity,
        token: String,
        userId: String,
        isSupplement: Boolean,
    ) {
        resetSumsub(token, userId, TYPE_POA) resetPoa@{ resetSuccess ->
            if (!resetSuccess) {
                hideLoading()
                AddressAuthActivity.startThis(activity, isSupplement)
                ActivityCollector.finishActivity(IdentityAuthActivity::class.java)
                return@resetPoa
            }
            //获取sumsub的poa身份认证token
            getTokenLaunchSumsub(activity, token, userId, TYPE_POA, isSupplement, false)
        }
    }


    private fun getTokenLaunchSumsub(
        activity: Activity,
        token: String,
        userId: String,
        type: Int,
        isSupplement: Boolean,
        isContinuePoa: Boolean,
    ) {
        getSumsubToken(activity, token, userId, type, isSupplement, isContinuePoa) { complete ->
            ActivityCollector.finishActivity(IdentityAuthActivity::class.java)
            ActivityCollector.finishActivity(AddressAuthActivity::class.java)
            if (complete) {
                notifySumsubComplete(type, token, userId, isSupplement)
            }
        }
    }

    private fun notifySumsubComplete(
        type: Int, token: String, userId: String, supplement: Boolean
    ) {
        val networkCallBack = object : IBaseCallBack<ResponseResult<Any?>> {
            override fun onResponse(response: ResponseResult<Any?>) {
                //更新用户信息
                GlobalInfoManager.getInstance().update(GlobalInfoManager.UPDATE_USR_INFO)
                GlobalInfoManager.getInstance()
                    .notify(HomeFragment::class.java, GlobalInfoManager.UPDATE_USR_INFO)
            }
        }
        if (type == TYPE_POI) {
            mKYCModel.notifyPoiResult(token, userId, supplement, networkCallBack)
        } else if (type == TYPE_POA) {
            mKYCModel.notifyPoaResult(token, userId, supplement, networkCallBack)
        }
    }

    private fun getSumsubToken(
        activity: Activity,
        token: String,
        userId: String,
        type: Int,
        supplement: Boolean,
        isContinuePoa: Boolean,
        callBack: (Boolean) -> Unit
    ) {
        requestSumsubToken(token, userId, type) { accessToken ->
            //如果获取Sumsub Token失败则，切手动上传
            if (accessToken == null) {
                //调取手动上传
                if (type == TYPE_POI) {
                    IdentityAuthActivity.startThisBySumsub(
                        activity, supplement, isContinuePoa
                    )
                } else if (type == TYPE_POA) {
                    AddressAuthActivity.startThis(activity, supplement)
                }
            } else {
                launchSumsub(activity, accessToken, callBack)
            }
        }
    }

    private fun launchSumsub(
        activity: Activity, accessToken: SumsubAccessToken, callBack: (Boolean) -> Unit
    ) {
        completedListener.callBack = callBack
        var appLanguageCode =
            SpUtils.getInstance().getString(CommonConstants.Key.KEY_APP_LANGUAGE_CODE)
        if (TextUtils.isEmpty(appLanguageCode)) {
            appLanguageCode = "en"
        }
        val snsSdk = SNSMobileSDK.Builder(activity).withAccessToken(
            accessToken.token, onTokenExpiration = tokenExpirationHandler
        ).withLocale(
            localMap[appLanguageCode] ?: Locale.ENGLISH
        ).withHandlers(
            onError = onSDKErrorHandler,
        ).withCompleteHandler(completedListener).withDebug(false).build()
        snsSdk.launch()
    }

    private fun requestSumsubToken(
        token: String, userId: String, type: Int, callBack: (SumsubAccessToken?) -> Unit
    ) {
        val netWorkCallBack = object : IBaseCallBack<ResponseResult<SumsubAccessToken>> {
            override fun onResponse(response: ResponseResult<SumsubAccessToken>) {
                hideLoading()
                if (response.code == ResponseResult.SUCCESS_CODE) {
                    response.data?.also {
                        callBack.invoke(it)
                    } ?: callBack.invoke(null)
                } else {
                    callBack.invoke(null)
                }
            }
        }
        if (type == TYPE_POI) {
            mKYCModel.getSumsubPoiToken(token, userId, netWorkCallBack)
        } else if (type == TYPE_POA) {
            mKYCModel.getSumsubPoaToken(token, userId, netWorkCallBack)
        }
    }

    private fun resetSumsub(
        token: String, userId: String, type: Int, callBack: (Boolean) -> Unit
    ) {
        val networkCallBack = object : IBaseCallBack<ResponseResult<Any?>> {
            override fun onResponse(response: ResponseResult<Any?>) {
                if (response.code == ResponseResult.SUCCESS_CODE) {
                    callBack.invoke(true)
                } else {
                    callBack.invoke(false)
                }
            }
        }
        if (type == TYPE_POI) {
            mKYCModel.resetSumsub(token, userId, networkCallBack)
        } else if (type == TYPE_POA) {
            mKYCModel.resetSumsubPoa(token, userId, networkCallBack)
        }
    }

    private fun showLoading(activity: Activity) {
        mLoadingDialog = LoadingDialog(activity)
        mLoadingDialog?.show()
    }

    private fun hideLoading() {
        if (mLoadingDialog != null && mLoadingDialog!!.isShowing) {
            mLoadingDialog?.dismiss()
            GlobalInfoManager.getInstance().notifyAll(GlobalInfoManager.FINISH_SELF)
        }
        mLoadingDialog = null
    }

}